<template>
  <div class="planX6-box">
    <div class="planX6-out-box">
      <div class="planX6-rigth-box">
        <div id="myPaletteDiv">
          <canvas
            tabindex="0"
            width="100%"
            height="100%"
            style="
              position: absolute;
              top: 0px;
              left: 0px;
              z-index: 2;
              user-select: none;
              width: 100%;
              height: 100%;
              cursor: auto;
            "
          ></canvas>
          <div
            style="
              position: absolute;
              overflow: auto;
              width: 100%;
              height: 100%;
              z-index: 1;
            "
          >
            <div style="position: absolute; width: 1px; height: 1px"></div>
          </div>
        </div>
        <div id="myDiagramDiv" ref="myDiagram">
          <canvas
            tabindex="0"
            width="100%"
            height="100%"
            style="
              position: absolute;
              top: 0px;
              left: 0px;
              z-index: 2;
              user-select: none;
              width: 100%;
              height: 100%;
              cursor: auto;
            "
          ></canvas>
          <div
            style="
              position: absolute;
              overflow: auto;
              width: 100%;
              height: 100%;
              z-index: 1;
            "
          >
            <div style="position: absolute; width: 1px; height: 1px"></div>
          </div>
        </div>
      </div>
      <div class="planX6-left-box">
        <div class="planX6-rigth-inner">
          <div class="planX6-inner-title">属性配置</div>
          <el-form ref="form" :model="currentNode" label-width="80px">
            <el-form-item label="源节点:">
              <el-select
                v-model="currentNode.source"
                multiple
                placeholder="请选择数据"
                @change="updateNodeProperty('source', currentNode.source)"
              >
                <el-option
                  :label="item.text"
                  :value="item.key"
                  v-for="(item, index) in filteredNodeData"
                  :key="'sslChoose' + index"
                ></el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="目标节点:">
              <el-input
                v-model="currentNode.text"
                @change="updateNodeProperty('text', currentNode.text)"
              ></el-input>
            </el-form-item>
            <el-form-item label="节点标识:">
              <el-input
                v-model="currentNode.key"
                @change="updateNodeProperty('key', currentNode.key)"
                disabled
              ></el-input>
            </el-form-item>
          </el-form>
        </div>
      </div>
    </div>
    <!-- <div class="popup-box" v-if="showPopup">
      <div class="planX6-inner-title">{{ currentNode.text }}</div>
      <div class="popup-icon" @click="closePopup()"></div>
      <div class="display-flex">
        <div class="popup-inner">
          目标：0
        </div>
        <div class="popup-inner">
          资源：0
        </div>
      </div>
      <div class="popup-button-box">
        <span class="popup-button-title">{{ currentNode.category == 'prototype' ? '数字样机' : currentNode.category == 'control' ?
          '控制系统' : currentNode.category ==
            'header' ? '导引头' : '' }} 指令</span>
        <i class="el-icon-circle-plus-outline blue-font3 marginRight5 cursor" @click="addOrder()"></i>
        <i class="el-icon-delete red-font1 cursor" @click="deleteOrder()"></i>
      </div>

    </div> -->
  </div>
</template>

<script>
import * as go from "gojs";
export default {
  name: "planX6",
  data() {
    return {
      showPopup: false,
      currentNode: {
        text: "",
        category: "",
      }, //当前node节点
      ssl: [],
      sslList: [
        {
          name: "SSL1",
        },
      ],
      myDiagram: null,
      myPalette: null,
      planData: {
        class: "GraphLinksModel",
        linkFromPortIdProperty: "fromPort",
        linkToPortIdProperty: "toPort",
        nodeDataArray: [
          {
            category: "prototype",
            text: "数字样机",
            key: -1,
            loc: "-185.875 -231.15625",
          },
          {
            category: "control",
            text: "导引头",
            key: -2,
            loc: "-30.109375 -137.390625",
          },
          {
            category: "header",
            text: "控制系统",
            key: -3,
            loc: "-192.109375 -134.390625",
          },
        ],
        linkDataArray: [
          { from: -3, to: -1, fromPort: "R", toPort: "L", points: [] },
        ],
      },
    };
  },
  computed: {
    filteredNodeData() {
      // 过滤掉当前节点的 key 值
      return this.myDiagram?.model.nodeDataArray.filter(
        (item) => item.key !== this.currentNode.key
      );
    },
  },
  mounted() {
    this.init();
  },
  methods: {
    //关闭节点指令弹窗
    closePopup() {
      this.showPopup = false;
    },
    //新增节点指令
    addOrder() {},
    //删除节点指令
    deleteOrder() {},
    // 更新节点的属性
    updateNodeProperty(property, value) {
      const node = this.myDiagram.findNodeForKey(this.currentNode.key);
      if (node) {
        node.data[property] = value;
        if (property == "source") {
          this.updateLinks(node);
        } else {
          this.save();
          this.load();
        }
      }
    },
    // 新增方法：根据当前节点更新连线
    updateLinks(node) {
      let that = this;
      const currentNodeKey = node.data.key;
      const sourceKeys = node.data.source;
      // 删除不再存在的连线
      this.removeUnwantedLinks(currentNodeKey, sourceKeys);
      // 添加新连线
      sourceKeys.forEach((sourceKey) => {
        if (!this.linkExists(sourceKey, currentNodeKey)) {
          that.myDiagram.model.linkDataArray.push({
            from: sourceKey,
            to: currentNodeKey,
            fromPort: "R",
            toPort: "L",
          });
        }
      });
      this.save();
      this.load();
      // 更新Diagram以反映更改
      // this.myDiagram.model = new go.GraphLinksModel(this.planData);
    },
    // 检查连线是否存在
    linkExists(fromKey, toKey) {
      return this.myDiagram.model.linkDataArray.some(
        (link) => link.from === fromKey && link.to === toKey
      );
    },
    // 移除不再需要的连线
    removeUnwantedLinks(targetKey, currentSources) {
      this.myDiagram.model.linkDataArray =
        this.myDiagram.model.linkDataArray.filter((link) => {
          if (link.to === targetKey && !currentSources.includes(link.from)) {
            // 如果连线的目标是当前节点，并且源节点不在当前选中的源节点列表中，则移除该连线
            return false;
          }
          return true;
        });
    },
    addSSL() {
      this.sslList.push({
        name: "SSL" + (this.sslList.length + 1),
      });
    },
    deleteSSL() {
      // 创建一个 Set 用于存储 ssl 中的名字
      const sslNamesSet = new Set(this.ssl.map((sslItem) => sslItem));
      // 使用 Set 进行快速查找
      this.sslList = this.sslList.filter((item) => !sslNamesSet.has(item.name));
    },
    init() {
      let that = this;
      if (window.goSamples) goSamples(); // init for these samples -- you don't need to call this
      var $ = go.GraphObject.make; // for conciseness in defining templates
      this.myDiagram = $(
        go.Diagram,
        "myDiagramDiv", // must name or refer to the DIV HTML element
        {
          LinkDrawn: showLinkLabel, // this DiagramEvent listener is defined below
          LinkRelinked: showLinkLabel,
          "undoManager.isEnabled": true, // enable undo & redo
        }
      );
      // when the document is modified, add a "*" to the title and enable the "Save" button
      this.myDiagram.addDiagramListener("Modified", function (e) {
        var button = document.getElementById("SaveButton");
        if (button) button.disabled = !that.myDiagram.isModified;
        var idx = document.title.indexOf("*");
        if (that.myDiagram.isModified) {
          if (idx < 0) document.title += "*";
        } else {
          if (idx >= 0) document.title = document.title.substr(0, idx);
        }
      });
      // helper definitions for node templates
      function nodeStyle() {
        return [
          // The Node.location comes from the "loc" property of the node data,
          // converted by the Point.parse static method.
          // If the Node.location is changed, it updates the "loc" property of the node data,
          // converting back using the Point.stringify static method.
          new go.Binding("location", "loc", go.Point.parse).makeTwoWay(
            go.Point.stringify
          ),
          {
            // the Node.location is at the center of each node
            locationSpot: go.Spot.Center,
          },
        ];
      }
      function makePort(name, align, spot, output, input) {
        var horizontal =
          align.equals(go.Spot.Top) || align.equals(go.Spot.Bottom);
        return $(go.Shape, {
          fill: "transparent", // changed to a color in the mouseEnter event handler
          strokeWidth: 0, // no stroke
          width: horizontal ? NaN : 8, // if not stretching horizontally, just 8 wide
          height: !horizontal ? NaN : 8, // if not stretching vertically, just 8 tall
          alignment: align, // align the port on the main Shape
          stretch: horizontal
            ? go.GraphObject.Horizontal
            : go.GraphObject.Vertical,
          portId: name, // declare this object to be a "port"
          fromSpot: spot, // declare where links may connect at this port
          fromLinkable: output, // declare whether the user may draw links from here
          toSpot: spot, // declare where links may connect at this port
          toLinkable: input, // declare whether the user may draw links to here
          cursor: "pointer", // show a different cursor to indicate potential link point
          mouseEnter: function (e, port) {
            // the PORT argument will be this Shape
            if (!e.diagram.isReadOnly) port.fill = "rgba(255,0,255,0.5)";
          },
          mouseLeave: function (e, port) {
            port.fill = "transparent";
          },
        });
      }
      function textStyle() {
        return {
          font: "bold 11pt Lato, Helvetica, Arial, sans-serif",
          stroke: "#F8F8F8",
        };
      }
      // 数字样机节点模板
      that.myDiagram.nodeTemplateMap.add(
        "prototype", // the default category
        $(
          go.Node,
          "Table",
          nodeStyle(),
          // the main object is a Panel that surrounds a TextBlock with a rectangular Shape
          $(
            go.Panel,
            "Auto",
            $(
              go.Shape,
              "Rectangle",
              { fill: "#d1cb00", stroke: "#595a00", strokeWidth: 3.5 },
              new go.Binding("figure", "figure")
            ),
            $(
              go.TextBlock,
              textStyle(),
              {
                margin: 10,
                maxSize: new go.Size(200, 100),
                wrap: go.TextBlock.WrapFit,
                editable: false,
              },
              new go.Binding("text").makeTwoWay()
            )
          ),
          // four named ports, one on each side:
          makePort("T", go.Spot.Top, go.Spot.TopSide, true, true),
          makePort("L", go.Spot.Left, go.Spot.LeftSide, true, true),
          makePort("R", go.Spot.Right, go.Spot.RightSide, true, true),
          makePort("B", go.Spot.Bottom, go.Spot.BottomSide, true, true),
          // 添加点击事件处理
          {
            click: function (e, node) {
              that.currentNode = node.data;
              if (that.currentNode.key && that.myDiagram) {
                that.currentNode.source = [];
                that.myDiagram.model.linkDataArray.forEach((link) => {
                  if (link.to == that.currentNode.key) {
                    that.currentNode.source.push(link.from);
                  }
                });
              }
              that.showPopup = true;
            },
            // 添加调整大小的Adornment
            resizeObjectName: "RESIZEHANDLE",
            // Adornment定义
            resizeAdornmentTemplate: $(
              go.Adornment,
              "Spot",
              $(go.Placeholder), // 必须包含一个 Placeholder
              $(
                go.Shape, // 调整大小的手柄
                {
                  geometryString: "M0 0 L8 4 L0 8 Z",
                  fill: "black",
                  stroke: "#fff", // 修改为透明颜色
                  cursor: "se-resize",
                },
                { name: "RESIZEHANDLE", alignment: new go.Spot(1, 1, -8, -8) }
              )
            ),
          }
        )
      );
      // 导引头节点模板
      that.myDiagram.nodeTemplateMap.add(
        "header", // the default category
        $(
          go.Node,
          "Table",
          nodeStyle(),
          // the main object is a Panel that surrounds a TextBlock with a rectangular Shape
          $(
            go.Panel,
            "Auto",
            $(
              go.Shape,
              "Rectangle",
              //背景颜色 边框颜色 边框宽度
              { fill: "#00d18d", stroke: "#005a39", strokeWidth: 3.5 },
              new go.Binding("figure", "figure")
            ),
            $(
              go.TextBlock,
              textStyle(),
              {
                margin: 10,
                maxSize: new go.Size(160, NaN),
                wrap: go.TextBlock.WrapFit,
                editable: false,
              },
              new go.Binding("text").makeTwoWay()
            )
          ),
          // four named ports, one on each side:
          makePort("T", go.Spot.Top, go.Spot.TopSide, true, true),
          makePort("L", go.Spot.Left, go.Spot.LeftSide, true, true),
          makePort("R", go.Spot.Right, go.Spot.RightSide, true, true),
          makePort("B", go.Spot.Bottom, go.Spot.BottomSide, true, true),
          // 添加点击事件处理
          {
            click: function (e, node) {
              that.currentNode = node.data;
              if (that.currentNode.key && that.myDiagram) {
                that.currentNode.source = [];
                that.myDiagram.model.linkDataArray.forEach((link) => {
                  if (link.to == that.currentNode.key) {
                    that.currentNode.source.push(link.from);
                  }
                });
              }
              that.showPopup = true;
            },
          }
        )
      );
      // 控制系统节点模板
      that.myDiagram.nodeTemplateMap.add(
        "control", // the default category
        $(
          go.Node,
          "Table",
          nodeStyle(),
          // the main object is a Panel that surrounds a TextBlock with a rectangular Shape
          $(
            go.Panel,
            "Auto",
            $(
              go.Shape,
              "Rectangle",
              { fill: "#ff0000", stroke: "#5a0000", strokeWidth: 3.5 },
              new go.Binding("figure", "figure")
            ),
            $(
              go.TextBlock,
              textStyle(),
              {
                margin: 10,
                maxSize: new go.Size(160, NaN),
                wrap: go.TextBlock.WrapFit,
                editable: false,
              },
              new go.Binding("text").makeTwoWay()
            )
          ),
          // four named ports, one on each side:
          makePort("T", go.Spot.Top, go.Spot.TopSide, true, true),
          makePort("L", go.Spot.Left, go.Spot.LeftSide, true, true),
          makePort("R", go.Spot.Right, go.Spot.RightSide, true, true),
          makePort("B", go.Spot.Bottom, go.Spot.BottomSide, true, true),
          // 添加点击事件处理
          {
            click: function (e, node) {
              that.currentNode = node.data;
              if (that.currentNode.key && that.myDiagram) {
                that.currentNode.source = [];
                that.myDiagram.model.linkDataArray.forEach((link) => {
                  if (link.to == that.currentNode.key) {
                    that.currentNode.source.push(link.from);
                  }
                });
              }
              that.showPopup = true;
            },
          }
        )
      );
      // 舵机节点模板
      that.myDiagram.nodeTemplateMap.add(
        "steeringEngine", // the default category
        $(
          go.Node,
          "Table",
          nodeStyle(),
          // the main object is a Panel that surrounds a TextBlock with a rectangular Shape
          $(
            go.Panel,
            "Auto",
            $(
              go.Shape,
              "Rectangle",
              //背景颜色 边框颜色 边框宽度
              { fill: "#667085", stroke: "#005a39", strokeWidth: 3.5 },
              new go.Binding("figure", "figure")
            ),
            $(
              go.TextBlock,
              textStyle(),
              {
                margin: 10,
                maxSize: new go.Size(160, NaN),
                wrap: go.TextBlock.WrapFit,
                editable: false,
              },
              new go.Binding("text").makeTwoWay()
            )
          ),
          // four named ports, one on each side:
          makePort("T", go.Spot.Top, go.Spot.TopSide, true, true),
          makePort("L", go.Spot.Left, go.Spot.LeftSide, true, true),
          makePort("R", go.Spot.Right, go.Spot.RightSide, true, true),
          makePort("B", go.Spot.Bottom, go.Spot.BottomSide, true, true),
          // 添加点击事件处理
          {
            click: function (e, node) {
              that.currentNode = node.data;
              if (that.currentNode.key && that.myDiagram) {
                that.currentNode.source = [];
                that.myDiagram.model.linkDataArray.forEach((link) => {
                  if (link.to == that.currentNode.key) {
                    that.currentNode.source.push(link.from);
                  }
                });
              }
              that.showPopup = true;
            },
          }
        )
      );
      // taken from ../extensions/Figures.js:
      go.Shape.defineFigureGenerator("File", function (shape, w, h) {
        var geo = new go.Geometry();
        var fig = new go.PathFigure(0, 0, true); // starting point
        geo.add(fig);
        fig.add(new go.PathSegment(go.PathSegment.Line, 0.75 * w, 0));
        fig.add(new go.PathSegment(go.PathSegment.Line, w, 0.25 * h));
        fig.add(new go.PathSegment(go.PathSegment.Line, w, h));
        fig.add(new go.PathSegment(go.PathSegment.Line, 0, h).close());
        var fig2 = new go.PathFigure(0.75 * w, 0, false);
        geo.add(fig2);
        // The Fold
        fig2.add(new go.PathSegment(go.PathSegment.Line, 0.75 * w, 0.25 * h));
        fig2.add(new go.PathSegment(go.PathSegment.Line, w, 0.25 * h));
        geo.spot1 = new go.Spot(0, 0.25);
        geo.spot2 = go.Spot.BottomRight;
        return geo;
      });
      // 连接线模板
      // replace the default Link template in the linkTemplateMap
      that.myDiagram.linkTemplate = $(
        go.Link, // the whole link panel
        {
          routing: go.Link.AvoidsNodes,
          curve: go.Link.JumpOver,
          corner: 5,
          toShortLength: 4,
          relinkableFrom: true,
          relinkableTo: true,
          reshapable: true,
          resegmentable: true,
          // mouse-overs subtly highlight links:
          mouseEnter: function (e, link) {
            link.findObject("HIGHLIGHT").stroke = "rgba(30,144,255,0.2)";
          },
          mouseLeave: function (e, link) {
            link.findObject("HIGHLIGHT").stroke = "transparent";
          },
          selectionAdorned: false,
        },
        new go.Binding("points").makeTwoWay(),
        $(
          go.Shape, // the highlight shape, normally transparent
          {
            isPanelMain: true,
            strokeWidth: 8,
            stroke: "transparent",
            name: "HIGHLIGHT",
          }
        ),
        $(
          go.Shape, // the link path shape
          { isPanelMain: true, stroke: "white", strokeWidth: 2 },
          new go.Binding("stroke", "isSelected", function (sel) {
            return sel ? "dodgerblue" : "white";
          }).ofObject()
        ),
        $(
          go.Shape, // the arrowheader
          { toArrow: "standard", strokeWidth: 0, fill: "white" }
        ),
        $(
          go.Panel,
          "Auto", // the link label, normally not visible
          {
            visible: false,
            name: "LABEL",
            segmentIndex: 2,
            segmentFraction: 0.5,
          },
          new go.Binding("visible", "visible").makeTwoWay(),
          $(
            go.Shape,
            "RoundedRectangle", // the label shape
            { fill: "#F8F8F8", strokeWidth: 0 }
          ),
          $(
            go.TextBlock,
            "Yes", // the label
            {
              textAlign: "center",
              font: "10pt helvetica, arial, sans-serif",
              stroke: "#333333",
              editable: true,
            },
            new go.Binding("text").makeTwoWay()
          )
        )
      );
      // Make link labels visible if coming out of a "conditional" node.
      // This listener is called by the "LinkDrawn" and "LinkRelinked" DiagramEvents.
      function showLinkLabel(e) {
        var label = e.subject.findObject("LABEL");
        if (label !== null)
          label.visible = e.subject.fromNode.data.category === "Conditional";
      }
      // temporary links used by LinkingTool and RelinkingTool are also orthogonal:
      that.myDiagram.toolManager.linkingTool.temporaryLink.routing =
        go.Link.Orthogonal;
      that.myDiagram.toolManager.relinkingTool.temporaryLink.routing =
        go.Link.Orthogonal;
      this.load(); // load an initial diagram from some JSON text
      // initialize the Palette that is on the left side of the page
      that.myPalette = $(
        go.Palette,
        "myPaletteDiv", // must name or refer to the DIV HTML element
        {
          // Instead of the default animation, use a custom fade-down
          "animationManager.initialAnimationStyle": go.AnimationManager.None,
          InitialAnimationStarting: animateFadeDown, // Instead, animate with this function
          nodeTemplateMap: that.myDiagram.nodeTemplateMap, // share the templates used by myDiagram
          model: new go.GraphLinksModel([
            // specify the contents of the Palette
            { category: "header", text: "导引头" },
            { category: "prototype", text: "数字样机" },
            { category: "control", text: "控制系统" },
            { category: "steeringEngine", text: "舵机" },
          ]),
        }
      );
      // This is a re-implementation of the default animation, except it fades in from downwards, instead of upwards.
      function animateFadeDown(e) {
        var diagram = e.diagram;
        var animation = new go.Animation();
        animation.isViewportUnconstrained = true; // So Diagram positioning rules let the animation start off-screen
        animation.easing = go.Animation.EaseOutExpo;
        animation.duration = 900;
        // Fade "down", in other words, fade in from above
        animation.add(
          diagram,
          "position",
          diagram.position.copy().offset(0, 200),
          diagram.position
        );
        animation.add(diagram, "opacity", 0, 1);
        animation.start();
      }
    },
    save() {
      this.planData = JSON.parse(this.myDiagram.model.toJson());
      this.myDiagram.isModified = false;
    },
    load() {
      this.myDiagram.model = go.Model.fromJson(this.planData);
    },
    send() {},
  },
};
</script>

<style scoped lang="scss">
.planX6-box {
  position: relative;

  .planX6-out-box {
    width: 100%;
    height: 70vh;
    display: flex;
    justify-content: space-between;
  }

  .planX6-rigth-box {
    width: 50%;
    height: 100%;
    background-color: var(--app-nav-bg);
  }

  .planX6-rigth-inner {
    border: 1px solid var(--ui-border-color-base);
    // background-color: ;
    margin: 5px;
    padding: 10px;
    height: 40%;
  }

  .planX6-left-box {
    width: 50%;
    height: 100%;
  }

  /* 可以在这里添加样式 */
  #myDiagramDiv {
    flex-grow: 1;
    height: calc(100% - 81px);
    position: relative;
    -webkit-tap-highlight-color: rgba(255, 255, 255, 0);
    cursor: auto;
  }

  #myPaletteDiv {
    height: 80px;
    margin-right: 2px;
    position: relative;
    -webkit-tap-highlight-color: rgba(255, 255, 255, 0);
    cursor: auto;
  }

  .sub-btn {
    width: 90px;
    height: 35px;
    line-height: 30px;
    text-align: center;
    background-image: url("/public/images/components/dialogSubBtn.png") !important;
    background-size: 100% 100%;
    cursor: pointer;
  }

  .sub-btn:hover {
    background-image: url("/public/images/components/dialogSubBtnAc.png") !important;
    background-size: 100% 100%;
  }

  .clo-btn {
    width: 90px;
    height: 35px;
    line-height: 30px;
    text-align: center;
    margin-left: 15px;
    background-image: url("/public/images/components/dialogCloseBtn.png") !important;
    background-size: 100% 100%;
    cursor: pointer;
  }

  .clo-btn:hover {
    background-image: url("/public/images/components/dialogCloseBtnAc.png") !important;
    background-size: 100% 100%;
  }

  .planX6-inner-title {
    font-weight: bold;
    margin: 5px auto;
    width: 160px;
    height: 14px;
    display: flex;
    justify-content: center;
    align-items: center;
    background-image: url("/public/images/components/smallTitle.png") !important;
    background-size: 100% 100%;
  }

  .planX6-checkbox {
    width: calc(100% - 40px);
    padding: 10px 0 10px 20px;
    margin: 0 10px;
  }

  .marginRight5 {
    margin-right: 5px;
  }

  .planX6-checkbox-box {
    height: calc(100% - 43px);
    overflow: auto;
  }

  .textAlignRight {
    text-align: right;
  }

  .cursor {
    cursor: pointer;
  }

  .popup-box {
    width: 250px;
    height: 450px;
    position: fixed;
    top: 20vh;
    right: 2vw;
    border: 1px solid #2b7798;
    background-color: #103141;
    z-index: 3;
  }

  .popup-icon {
    height: 16px;
    width: 16px;
    background: url("/public/images/components/dialogCloseIcon.png") no-repeat;
    background-size: cover;
    position: absolute;
    top: 5px;
    right: 5px;
    cursor: pointer;
  }

  .popup-inner {
    width: 45%;
    height: 3.5vh;
    background-image: url("/public/images/components/suanFa.png") !important;
    background-size: 100% 100%;
    line-height: 3.5vh;
    text-align: center;
    font-size: 16px;
    font-weight: bold;
  }

  .display-flex {
    display: flex;
    justify-content: space-around;
    padding: 5px 0;
    border-bottom: 1px solid #2b7798;
  }

  .popup-button-box {
    padding: 5px;
  }

  .popup-button-title {
    display: inline-block;
    width: calc(100% - 40px);
  }
}
</style>